/*
    2D FDTD simulator
    Copyright (C) 2019 Emilia Blåsten

    This program is free software: you can redistribute it and/or
    modify it under the terms of the GNU Affero General Public License
    as published by the Free Software Foundation, either version 3 of
    the License, or (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public
    License along with this program.  If not, see
    <http://www.gnu.org/licenses/>.
*/
/* tmzdemo2.c: Program to perform a TMz simulation where the field is 
 * introduced via a TFSF boundary and the grid is terminated with a 
 * second order ABC. */

#include <stdio.h>
#include <stdlib.h> //for calloc
#include "ezinc.h"
#include "plotWindow.h"
#include "plot2d.h"
#include "tfsftmz.h"
#include "updatetmz.h"
#include "gridtmz.h"
#include "abctmz.h"
#include "source.h"

int main()
{
  int WIDTH = 640;
  int HEIGHT = 480;

  plotWindow *window1 = createPlotWindow(0,100,WIDTH, HEIGHT, "Total Ez-field");
  plotWindow *window2 = createPlotWindow(WIDTH+5,100,WIDTH, HEIGHT, "Incident Ez-field");
  plotWindow *window3 = createPlotWindow(2*WIDTH+10,100,WIDTH, HEIGHT, "Scattered Ez-field");

  // allocate memory for grids
  Grid *gTotal, *gIncid;
  gTotal = gridCreate(WIDTH, HEIGHT);
  gIncid = gridCreate(WIDTH, HEIGHT);
  // Initialize field values and parameters
  gridInit(gTotal, 3);
  gridInit(gIncid, -1);

  // initialize ABC
  Abc *abTot, *abInc;
  abTot = abcCreate(gTotal->sizeX, gTotal->sizeY);
  abInc = abcCreate(gTotal->sizeX, gTotal->sizeY);
  abcInit(abTot, gTotal);
  abcInit(abInc, gIncid);

  // initialize TFSF
  Tfsf *tfTot, *tfInc;
  tfTot = tfsfCreate(gTotal->sizeX);
  tfInc = tfsfCreate(gIncid->sizeX);
  tfsfInit(tfTot, gTotal);
  tfsfInit(tfInc, gIncid);

  // do time stepping
  for( gTotal->time = 0; gTotal->time < gTotal->maxTime; gTotal->time++) {
    // update magnetic fields
    updateH2d(gTotal);
    updateH2d(gIncid);
    // apply TFSF boundary
    tfsfUpdate(tfTot, gTotal);
    tfsfUpdate(tfInc, gIncid);
    // update electric fields
    updateE2d(gTotal);
    updateE2d(gIncid);

    // add source term
    addSrc(gTotal);

    // apply ABC
    abc(abTot, gTotal);
    abc(abInc, gIncid);

    // draw the current Ez field
    plot2d(gTotal->ez, WIDTH, HEIGHT, window1);
    plot2d(gIncid->ez, WIDTH, HEIGHT, window2);
    plot2dLinComb(1, gTotal->ez, -1, gIncid->ez, WIDTH, HEIGHT, window3);

    // check to see if we should stop
    if(wantToStopPlot()) break;
  }

  // close the windows and free their memory
  destroyPlotWindow(window1);
  destroyPlotWindow(window2);
  destroyPlotWindow(window3);
  // free memory and safely shut SDL down
  quitAllPlotting();
  // free memory used by TFSF boundary
  tfsfDestroy(tfTot);
  tfsfDestroy(tfInc);
  // free memory used by ABC boundary
  abcDestroy(abTot);
  abcDestroy(abInc);
  // free memory allocated for Grid
  gridDestroy(gTotal);
  gridDestroy(gIncid);

  return 0;
}
